var ejs = require('ejs');
var fs = require('fs');
var path = require('path');
var config = require(__dirname + '/../config');
var _ = require('lodash');
var moment = require('moment');

module.exports = {
    promisify: function (fn, receiver) {
        return (...args) => {
            return new Promise((resolve, reject) => {
                fn.apply(receiver, [...args, (err, res) => {
                    return err ? reject(err) : resolve(res);
                }]);
            });
        };
    },
    objectToString: function (o) {
        return Object.prototype.toString.call(o);
    },
    isArray: function (arg) {
        if (Array.isArray) {
            return Array.isArray(arg);
        }
        return this.objectToString(arg) === '[object Array]';
    },
    isBoolean: function (arg) {
        return typeof arg === 'boolean';
    },
    isBuffer: function (arg) {
        return Buffer.isBuffer(arg);
    },
    isInt: function (value) {
        if (isNaN(value) || this.isString(value)) {
            return false;
        }
        var x = parseFloat(value);
        return (x | 0) === x;
    },
    isNull: function (arg) {
        return arg === null;
    },
    isNumber: function (arg) {
        return typeof arg === 'number';
    },
    isString: function (arg) {
        return typeof arg === 'string';
    },
    isNumberString: function (obj) {
        if (!obj) return false;
        const numberReg = /^((-?(\d+\.|\d+|\.\d)\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i;
        return numberReg.test(obj);
    },
    isSymbol: function (arg) {
        return typeof arg === 'symbol';
    },
    isUndefined: function (arg) {
        return arg === void 0;
    },
    isRegExp: function (re) {
        return this.objectToString(re) === '[object RegExp]';
    },
    isDate: function (d) {
        return this.objectToString(d) === '[object Date]';
    },
    isError: function (e) {
        return (this.objectToString(e) === '[object Error]' || e instanceof Error);
    },
    isFunction: function (arg) {
        return typeof arg === 'function';
    },
    isObject: function (arg) {
        return Object.prototype.toString.call(arg) === '[object Object]';
    },
    isEmpty: function (obj) {
        if (this.isTrueEmpty(obj)) return true;
        if (this.isRegExp(obj)) {
            return false;
        } else if (this.isDate(obj)) {
            return false;
        } else if (this.isError(obj)) {
            return false;
        } else if (this.isArray(obj)) {
            return obj.length === 0;
        } else if (this.isString(obj)) {
            return obj.length === 0;
        } else if (this.isNumber(obj)) {
            return obj === 0;
        } else if (this.isBoolean(obj)) {
            return !obj;
        } else if (this.isObject(obj)) {
            for (const key in obj) {
                return false && key; // only for eslint
            }
            return true;
        }
        return false;
    },
    isTrueEmpty: function (obj) {
        if (obj === undefined || obj === null || obj === '') return true;
        if (this.isNumber(obj) && isNaN(obj)) return true;
        return false;
    },
    msg: function (code, msg = '', url = '') {
        if (code) {
            if (!msg) msg = '操作成功';
        }
        if (!code) {
            if (!msg) msg = '操作失败';
        }
        var str = fs.readFileSync(this.viewPath + 'msg.html', 'utf-8');
        return ejs.render(str, { code: code, msg: msg, url: url });
    },
    unix2human: function (number) {
        if (!number) return '';
        return moment(number * 1000).format("YYYY-MM-DD HH:mm:ss");
    },
    human2unix: function (string) {
        if (!string) return '';
        return parseInt(new Date(string).getTime() / 1000)
    },
    model: function (name) {
        var m = require(this.modelPath + name + '.js');
        return new m();
    },
    rootPath: path.normalize(__dirname + '/../'),
    appPath: path.normalize(__dirname + '/../application/'),
    modelPath: path.normalize(__dirname + '/../application/models/'),
    viewPath: path.normalize(__dirname + '/../application/views/'),
    controllerPath: path.normalize(__dirname + '/../application/controllers/'),
    runtimePath: path.normalize(__dirname + '/../runtime/'),
    tableCachePath: path.normalize(__dirname + '/../runtime/table/'),
    uploadsPath: path.normalize(__dirname + '/../public/uploads/'),
    publicPath: path.normalize(__dirname + '/../public/'),

    lodash: _,
    moment: moment,

};